import datetime
import pytz
import json

from django.shortcuts import redirect, get_object_or_404
from django.http import Http404, HttpResponse
from django.urls import reverse_lazy
from django.views.generic import CreateView, UpdateView, DetailView, View
from django.views.generic.dates import MonthArchiveView
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.core.serializers.json import DjangoJSONEncoder

from django.conf import settings

from ..models import ShiftSchedule, LabLog
from ..forms import LabLogModelForm


class LabLogMonthArchiveView(MonthArchiveView):
    model = LabLog
    ordering = ['-log_date', '-log_time']
    date_field = 'log_date'
    month_format = '%m'
    allow_empty = True
    allow_future = False

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data(**kwargs)
        now = timezone.localtime(timezone.now())
        has_today_am_log = LabLog.objects.filter(log_date=now.date(), time_slot=1).exists()
        has_today_pm_log = LabLog.objects.filter(log_date=now.date(), time_slot=2).exists()

        context['now'] = now
        context['has_today_am_log'] = has_today_am_log  # 是否已经添加上午日志
        context['has_today_pm_log'] = has_today_pm_log  # 是否已经添加下午日志
        return context


class LabLogDetailView(DetailView):
    model = LabLog
    context_object_name = 'lablog'
    template_name = 'logs/lablog_detail.html'


@method_decorator(login_required, name='dispatch')
class CreateLabLogView(CreateView):
    model = LabLog
    form_class = LabLogModelForm
    template_name = 'logs/create_or_update_lablog.html'

    def get_success_url(self):
        return reverse_lazy('lablog_by_month',
                            kwargs={'year': self.kwargs.get('year'), 'month': self.kwargs.get('month')})

    def get(self, request, *args, **kwargs):
        try:
            slot = int(kwargs.get('slot'))
            year = self.kwargs['year']
            month = self.kwargs['month']
            day = self.kwargs['day']
            date = datetime.datetime(year=year, month=month, day=day, hour=0, minute=0, second=0,
                                     tzinfo=datetime.timezone(datetime.timedelta(hours=8)))

        except ValueError:
            raise Http404("日期格式不正确！")

        if timezone.localtime(date) > timezone.localtime(timezone.now()) \
                or timezone.localtime(date) + timezone.timedelta(hours=35) < timezone.localtime(timezone.now()):
            raise Http404("超出日志提交时限！")

        if slot == 2 and timezone.localtime(timezone.now()) <= (
                timezone.localtime(date) + timezone.timedelta(hours=12)):
            raise Http404("日志还不能添加！")

        log_pk = LabLog.objects.filter(log_date=date, time_slot=slot)

        if log_pk:
            return redirect('update_lablog', pk=log_pk)

        return super().get(request, *args, **kwargs)

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        year = self.kwargs.get('year')
        month = self.kwargs.get('month')
        day = self.kwargs.get('day')
        try:
            log_date = datetime.date(year=year, month=month, day=day)
        except ValueError:
            raise Http404("日期格式不正确！")

        time_slot = self.kwargs.get('slot')
        schedule = get_object_or_404(ShiftSchedule, duty_date=log_date)
        is_sign_in = False
        if schedule is not None and schedule.actual_duty_person is not None:
            is_sign_in = True

        kwargs.update({
            'log_date': log_date,
            'time_slot': time_slot,
            'is_sign_in': is_sign_in,
        })
        return kwargs

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        year = self.kwargs.get('year')
        month = self.kwargs.get('month')
        day = self.kwargs.get('day')
        try:
            log_date = datetime.date(year=year, month=month, day=day)
        except ValueError:
            raise Http404("日期格式不正确！")

        context['log_date'] = log_date
        context['time_slot'] = int(self.kwargs.get('slot'))
        context['schedule'] = ShiftSchedule.objects.get(duty_date=log_date)
        context['create_or_update'] = 1
        context['mode'] = 2
        return context

    def form_valid(self, form):
        lablog = form.save(commit=False)
        year = self.kwargs.get('year')
        month = self.kwargs.get('month')
        day = self.kwargs.get('day')

        if self.request.user:
            lablog.created_by = self.request.user
        lablog.created_at = timezone.now()
        lablog.log_date = datetime.datetime.strptime('{year}{month}{day}'.format(year=year, month=month, day=day),
                                                     '%Y%m%d')
        lablog.time_slot = int(self.kwargs.get('slot'))
        lablog.adding_way = 3
        lablog.save()
        return super().form_valid(form)


@method_decorator(login_required, name='dispatch')
class UpdateLabLogView(UpdateView):
    model = LabLog
    form_class = LabLogModelForm
    # success_url = reverse_lazy('lablog_by_month')
    template_name = 'logs/create_or_update_lablog.html'

    def get_success_url(self):
        return reverse_lazy('lablog_by_month',
                            kwargs={'year': self.kwargs.get('year'), 'month': self.kwargs.get('month')})

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        log_date = self.object.log_date
        time_slot = self.object.time_slot

        schedule = get_object_or_404(ShiftSchedule, duty_date=log_date)
        is_sign_in = False
        if schedule is not None and schedule.actual_duty_person is not None:
            is_sign_in = True

        kwargs.update({
            'log_date': log_date,
            'time_slot': time_slot,
            'is_sign_in': is_sign_in,
        })
        return kwargs

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        log_date = self.object.log_date
        context['log_date'] = log_date
        context['time_slot'] = self.object.time_slot
        context['schedule'] = ShiftSchedule.objects.get(duty_date=log_date)
        context['create_or_update'] = 2
        context['mode'] = 2
        return context

    def get_object(self, queryset=None):

        year = self.kwargs['year']
        month = self.kwargs['month']
        day = self.kwargs['day']
        slot = self.kwargs['slot']
        try:
            date = datetime.date(year=year, month=month, day=day)
        except ValueError:
            raise Http404("日期格式不正确！")

        obj = LabLog.objects.get(log_date=date, time_slot=slot)
        # 判断添加日志的日期为当天到第二天早上10:00
        if obj.is_overdue:
            raise Http404("超出日志修改时限！")

        return obj

    def form_valid(self, form):
        lablog = form.save(commit=False)

        lablog.updated_by = self.request.user
        lablog.last_updated = timezone.now()
        if lablog.adding_way == 1:
            lablog.adding_way = 2

        lablog.save()
        return super().form_valid(form)


def ajax_server_now(request):
    '''
    提供ajax定时获取服务器时间
    :param request:
    :return:
    '''
    if request.method == "GET":
        name_dict = {'server_time': timezone.localtime(timezone.now())}
        return HttpResponse(json.dumps(name_dict, sort_keys=True, indent=1, cls=DjangoJSONEncoder),
                            content_type='application/json')
